package docent;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PushbackReader;

public class MyPushbackReader
extends PushbackReader
{
  //
  // BOM = Byte Order Mark
  // FE FF 00 3C = UTF-16, big-endian
  // FF FE 3C 00 = UTF-16, little-endian
  // EF BB BF    = UTF-8
  //
    
  /*****************************************************************\
   Static
  \*****************************************************************/ 
  public static final char UTF_8 = '\uFEFF'; // BOM
  
  /*****************************************************************\
   private Attributes
  \*****************************************************************/ 
  private int lineNumber = 1;
  
  /*****************************************************************\
   Contruction
  \*****************************************************************/ 
  public MyPushbackReader(String filename)
  throws Exception
  {
    super(new InputStreamReader(new FileInputStream(new File(filename)), "UTF-8"));   
    int i = read();
    if (i == -1) throw new Exception("eof");
    char c = (char)i;    
    if (c != UTF_8) throw new Exception("no UTF-8 byte order mark");
  }
  
  /*****************************************************************\
   nextToken
  \*****************************************************************/ 
  public String nextToken()
  throws Exception
  {
    int c = nextChar();
    if (c == -1) return null;
    String token = ""+(char)c;
    if ((char)c == '<')
    {
      do
      {
        while ((c = read()) != -1 && c != '>') 
          token += (char)c;
        token += (char)c;  
      }
      while (token.startsWith("<![CDATA[") && token.indexOf("]]>")==-1);
    }
    else
    {
      while ((c = read()) != -1 && c != '<') 
        token += (char)c;
      unread(c);  
    }
    if (token.length() == 0) return null; 
    return token;
  }
  
  private int nextChar()
  throws Exception
  {
    int i = read();
    if (i == -1) return -1;
    switch (i)
    {
      case 10: lineNumber++; // new line
      case  9:               // horizontal tab
      case 13:               // cariage return
      case 32:               // space
               return nextChar(); 
    }
    return i;
  } 
  /*****************************************************************\
   get
  \*****************************************************************/ 
  public int getLineNumber() { return lineNumber; }
}